package com.example.BMS_Disp_1;

import java.util.Random;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class BatteryDB {
	public static final String KEY_TITLE = "title";
	public static final String KEY_CONFIG_NAME = "name";
	public static final String KEY_CONFIG_VALUE = "value";
	public static final String KEY_VOLTAGE_VALUE = "value";
	public static final String KEY_CHECKED = "checked";
	public static final String KEY_ROWID = "_id";
	public static final String KEY_CELL_ID = "id";
	public static boolean mFirstTimeInstall = false;

	private static final String TAG = "BMS_Disp";
	private static BatteryDB singleton;
	private static boolean mDebug = true;
	
	// current list id. set to default list by default.
	public long mCurrentListId = 0;

	private DatabaseHelper mDbHelper;
	private SQLiteDatabase mDb;

	/**
	 * Database creation definitions
	 */
	private static final String DATABASE_NAME = "MorganDB";
	private static final String TABLE_CONFIG = "config";
	private static final String TABLE_VOLTAGES = "voltages";
	private static final int DATABASE_VERSION = 1;

	private static final String CONFIG_CREATE_SQL = "CREATE TABLE "
			+ TABLE_CONFIG + "( " + KEY_ROWID
			+ " integer primary key autoincrement, " + KEY_CONFIG_NAME
			+ " text not null unique, " + KEY_CONFIG_VALUE + " text not null);";

	private static final String VOLTAGES_CREATE_SQL = "CREATE TABLE "
			+ TABLE_VOLTAGES + " ( " + KEY_ROWID
			+ " integer primary key autoincrement, " + KEY_CELL_ID + " integer not null unique, "
			+ KEY_VOLTAGE_VALUE + " float not null);";

	private static final String CONFIG_QUERY = "SELECT " + KEY_CONFIG_VALUE + 
		" FROM " + TABLE_CONFIG	+ " WHERE " + KEY_CONFIG_NAME + "=";

	private static final String VOLTAGES_QUERY = "SELECT " + KEY_VOLTAGE_VALUE + 
	" FROM " + TABLE_VOLTAGES + " WHERE " + KEY_CELL_ID + "=";

	private final Context mCtx;

	private static class DatabaseHelper extends SQLiteOpenHelper {

		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			Log.i(TAG, "onCreate: " + CONFIG_CREATE_SQL);
			db.execSQL(CONFIG_CREATE_SQL);

			Log.i(TAG, "onCreate: Voltages: " + VOLTAGES_CREATE_SQL);
			db.execSQL(VOLTAGES_CREATE_SQL);

			mFirstTimeInstall = true;
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONFIG + ";");
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_VOLTAGES + ";");
			onCreate(db);
		}
	}

	public static BatteryDB getSingleton(Context ctx) {
		if (singleton == null) {
			singleton = new BatteryDB(ctx);
		}
		return singleton;
	}
	/**
	 * Constructor - takes the context to allow the database to be
	 * opened/created
	 * 
	 * @param ctx
	 *            the Context within which to work
	 */
	private BatteryDB(Context ctx) {
		this.mCtx = ctx;
	}

	/**
	 * Open the database. If it cannot be opened, try to create a new
	 * instance of the database. If it cannot be created, throw an exception to
	 * signal the failure
	 * 
	 * @return this (self reference, allowing this to be chained in an
	 *         initialization call)
	 * @throws SQLException
	 *             if the database could be neither opened or created
	 */
	public BatteryDB open() throws SQLException {
		mDbHelper = new DatabaseHelper(mCtx);
		mDb = mDbHelper.getWritableDatabase();
		if (mFirstTimeInstall) {
			install();
			Log.i(TAG, "BatteryDB.open, first time install done.");
			mFirstTimeInstall = false;
		}
		return this;
	}

	public void close() {
		mDbHelper.close();
		mDb.close();
	}

	/*
	 * insert into  config (name,value) values('count','12');
	 * insert into voltages(id,value) values(i,3.2);
	 */
	
	public void install() {
		if (!mDebug) {
			return;
		}
		
		mDb.beginTransaction();
		try {
			mDb.execSQL("insert into config (name,value) values('count',12);");
			Random r = new Random(294820);
			for (int i=1;i<=12;i++) {
				double val = (r.nextInt(25))/10.0 + 1.0;
				String s = new String("insert into voltages(id,value) values(" + i + "," + val +");");
				mDb.execSQL(s);
			}
			mDb.setTransactionSuccessful();
		} finally {
			mDb.endTransaction();
		}
	}

	// Return Value of Config variable.
	public int getConfigValue(String name) {
		int id = -1;
		String[] args = {DatabaseUtils.sqlEscapeString(name.toLowerCase())};
		Log.i(TAG, "getConfigValue:" + CONFIG_QUERY);
		Cursor c = null;
		try {
			c = mDb.rawQuery(CONFIG_QUERY + args[0],null);					
			if (c.getCount() != 1) {
				Log.e(TAG, "getConfigValue - No Config for: " + name);
				return -1;
			}
			c.moveToFirst();
			id = c.getInt(c.getColumnIndexOrThrow(KEY_CONFIG_VALUE));
		} catch (Exception exc) {
			Log.e(TAG, "getConfigValue, Name=" + name + ":"+ exc.getMessage());
		} finally {
			if (c != null)
				c.close();
		}

		Log.d(TAG, "getConfigValue, id=" + id);
		return id;
	}
	
	// Set Value of a config variable. Overwrite if already there.
	public boolean setConfigValue(String pName, int value) {
		ContentValues cvals = new ContentValues();
		String name = DatabaseUtils.sqlEscapeString(pName.toLowerCase());
		cvals.put(KEY_CONFIG_NAME, name.toLowerCase());
		cvals.put(KEY_CONFIG_VALUE, value);
		mDb.beginTransaction();
		try {
			mDb.delete(TABLE_CONFIG, KEY_CONFIG_NAME +"=*", null);
			// ignore if delete fails.
				
			if (mDb.insert(TABLE_CONFIG,null, cvals) > 0) {		
				mDb.setTransactionSuccessful();
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			Log.e(TAG, "setConfigValue, exc: " + e.toString());
			return false;
		}finally {
			mDb.endTransaction();
		}
	}

	public double getVoltage(int id) {
		double voltage = -1;
		String args[] = {Integer.toString(id)};
		Cursor c=null;
		try {
			c = mDb.rawQuery(VOLTAGES_QUERY + args[0],null);
			if (c.getCount() != 1) {
				Log.e(TAG, "getVoltage - No Voltage for: " + id);
				return -1;
			}
			c.moveToFirst();
			voltage = c.getDouble(c.getColumnIndexOrThrow(KEY_VOLTAGE_VALUE));
		} catch (Exception exc) {
			Log.e(TAG, "getVoltage id=" + id + ":" + exc.getMessage());
		} finally {
			if (c!=null) c.close();
		}
	
		Log.d(TAG, "getVoltage: [id:voltage]=" + id + ":" + voltage);
		return voltage;
	}

	public boolean setVoltage(int id, double value) {
		ContentValues cvals = new ContentValues();
		Log.d(TAG,"setVoltage, cell:" + id + ",voltage:" + value);
		cvals.put(KEY_CELL_ID, id);
		cvals.put(KEY_VOLTAGE_VALUE, value);
		mDb.beginTransaction();
		try {
			mDb.delete(TABLE_VOLTAGES, KEY_CELL_ID +"=" + id, null);
			// ignore if delete fails.
				
			if (mDb.insert(TABLE_VOLTAGES, null, cvals) > 0) {
				mDb.setTransactionSuccessful();
				Log.d(TAG,"setVoltage - ok");
				return true;
			} else {
				return false;
			}
		} catch (Exception exc) {
			Log.e(TAG, "setVoltage, exc: " + exc.toString());
			return false;
		}
		finally {
			mDb.endTransaction();
		}
	}
}
